﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Assist;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YJKArchUtils.Utils;
using YJKRevitBase.WinForm;
using YJKRevitKernel.RevitDimensionUtility;
using YJKRevitDimensionText.CommandSetUtility;
using YJKRevitDimensionText.Forms;
using YJKRevitView;

namespace YJKRevitDimensionText.Commands
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	internal class CmdLabelLevel : IExternalCommand
	{
		[DllImport("user32.dll", EntryPoint = "SendMessageA")]
		public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

		public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
            CmdViewType cmdViewType = (CmdViewType)96;
			if (SwitchView.SetUsableView(cmdViewType, cmdData) != Autodesk.Revit.UI.Result.Succeeded)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			Autodesk.Revit.DB.View activeView = cmdData.Application.ActiveUIDocument.ActiveView;
			if (!ViewHandle.ViewValidating(cmdData.Application.ActiveUIDocument.Document, activeView, ref message))
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			this.m_doc = cmdData.Application.ActiveUIDocument.Document;
			this.m_selection = cmdData.Application.ActiveUIDocument.Selection;
			RevitVersionFuncs.ClearSelection(this.m_selection);
			if (CmdLabelLevel._hWndRevit == null)
			{
                CmdLabelLevel._hWndRevit = new WindowHandle(Process.GetCurrentProcess().MainWindowHandle);
			}
			LabelLevelForm labelLevelForm = new LabelLevelForm(cmdData);
			labelLevelForm.Show(CmdLabelLevel._hWndRevit);
			int wMsg = 7;
			CmdLabelLevel.SendMessage(CmdLabelLevel._hWndRevit.Handle, wMsg, IntPtr.Zero, IntPtr.Zero);
			Transaction transaction = new Transaction(this.m_doc, "LabelLevel");
			Result result;
			for (;;)
			{
				transaction.Start();
				LevelFilter levelFilter = new LevelFilter();
				IList<Element> list = null;
				XYZ ptLabel = XYZ.Zero;
				try
				{
					list = this.m_selection.PickElementsByRectangle(levelFilter, "请框选标高");
					if (list.Count < 2)
					{
						transaction.RollBack();
						continue;
					}
					ptLabel = this.m_selection.PickPoint("请选择标注位置：");
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					transaction.RollBack();
					labelLevelForm.Close();
					result = Autodesk.Revit.UI.Result.Succeeded;
					break;
				}
				catch (Exception ex)
				{
					string message2 = ex.Message;
					transaction.RollBack();
					labelLevelForm.Close();
					result = Autodesk.Revit.UI.Result.Failed;
					break;
				}
				try
				{
					this.LabelLevel(list, ptLabel, labelLevelForm.LabelStyle, labelLevelForm.LabelMode);
				}
				catch (Exception)
				{
					transaction.RollBack();
					labelLevelForm.Close();
					result = Autodesk.Revit.UI.Result.Failed;
					break;
				}
				transaction.Commit();
			}
			return result;
		}

		private void LabelLevel(IList<Element> arElement, XYZ ptLabel, string strStyle, int nMode)
		{
			if (2 == arElement.Count)
			{
				nMode = 2;
			}
			List<Level> list = new List<Level>();
			ReferenceArray referenceArray = new ReferenceArray();
			foreach (Element element in arElement)
			{
				Level level = element as Level;
				if (level != null)
				{
					list.Add(level);
					referenceArray.Append(new Reference(level));
				}
			}
			XYZ xyz = new XYZ(ptLabel.X, ptLabel.Y, list[0].Elevation);
			XYZ xyz2 = new XYZ(ptLabel.X, ptLabel.Y, list[list.Count - 1].Elevation);
			Line line = Line.CreateBound(xyz, xyz2);
			Transform inverse = this.m_doc.ActiveView.CropBox.Transform.Inverse;
			XYZ xyz3 = this.m_doc.ActiveView.RightDirection;
			BoundingBoxXYZ boundingBoxXYZ = list[0].get_BoundingBox(this.m_doc.ActiveView);
			ptLabel = inverse.OfPoint(ptLabel);
			XYZ xyz4 = inverse.OfPoint(boundingBoxXYZ.Max);
			XYZ xyz5 = inverse.OfPoint(boundingBoxXYZ.Min);
			if (xyz4.X < xyz5.X)
			{
				xyz4 = inverse.OfPoint(boundingBoxXYZ.Min);
				xyz5 = inverse.OfPoint(boundingBoxXYZ.Max);
			}
			if (Math.Abs(ptLabel.X - xyz5.X) < Math.Abs(ptLabel.X - xyz4.X))
			{
				xyz3 = xyz3.Negate();
			}
			DimensionType dimensionType = this.GetDimTypeByName(this.m_doc, strStyle);
			if (dimensionType == null && strStyle == "HY-轴线标注")
			{
                dimensionType = RevitDimensionUtiltyMethod.GetDimensionType(this.m_doc, (DimensionTypeEnum)1, null);
			}
			if (nMode == 0)
			{
				ReferenceArray references = this.m_doc.Create.NewDimension(this.m_doc.ActiveView, line, referenceArray, dimensionType).References;
				ReferenceArray referenceArray2 = new ReferenceArray();
                Reference reference = references.get_Item(0);
				Reference reference2 = references.get_Item(references.Size - 1);
				foreach (object obj in referenceArray)
				{
					Reference reference3 = (Reference)obj;
					if (reference3.ElementId == reference.ElementId || reference3.ElementId == reference2.ElementId)
					{
						referenceArray2.Append(reference3);
					}
				}
				double num = dimensionType.get_Parameter(BuiltInParameter.TEXT_SIZE).AsDouble() * 300.0;
				xyz += xyz3 * num;
				xyz2 += xyz3 * num;
				line = Line.CreateBound(xyz, xyz2);
				this.m_doc.Create.NewDimension(this.m_doc.ActiveView, line, referenceArray2, dimensionType);
				return;
			}
			if (1 == nMode)
			{
				Dimension dimension = this.m_doc.Create.NewDimension(this.m_doc.ActiveView, line, referenceArray, dimensionType);
				ReferenceArray references2 = dimension.References;
				ReferenceArray referenceArray3 = new ReferenceArray();
                Reference reference4 = references2.get_Item(0);
				Reference reference5 = references2.get_Item(references2.Size - 1);
				foreach (object obj2 in referenceArray)
				{
					Reference reference6 = (Reference)obj2;
					if (reference6.ElementId == reference4.ElementId || reference6.ElementId == reference5.ElementId)
					{
						referenceArray3.Append(reference6);
					}
				}
				this.m_doc.Create.NewDimension(this.m_doc.ActiveView, line, referenceArray3, dimensionType);
				this.m_doc.Delete(dimension.Id);
				return;
			}
			if (2 == nMode)
			{
				this.m_doc.Create.NewDimension(this.m_doc.ActiveView, line, referenceArray, dimensionType);
			}
		}

		private DimensionType GetDimTypeByName(Autodesk.Revit.DB.Document doc, string name)
		{
			foreach (DimensionType dimensionType in Common.GetDimensionTypes(this.m_doc))
			{
				if (dimensionType.Name.ToString().Equals(name) && dimensionType.StyleType == null)
				{
					return dimensionType;
				}
			}
			return null;
		}

		private Document m_doc;

		private Selection m_selection;

        public static WindowHandle _hWndRevit;
	}
}
